package edu.zjut.day3;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;

public class ProxyTest {

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception{
		Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
		System.out.println(clazzProxy1.getName());
		
		System.out.println("==========begin constructors list=============");
		/*
		$IProxy();
		$IProxy(InvocationHandler handler);
		*/
		Constructor[] constructors = clazzProxy1.getConstructors();
		for(Constructor constructor:constructors){
			String name = constructor.getName();
			StringBuilder sBuilder = new StringBuilder(name);
			sBuilder.append("(");
			Class[] clazzParams = constructor.getParameterTypes();
			for(Class clazz:clazzParams){
				sBuilder.append(clazz.getName()).append(",");;
			}
			if(clazzParams!=null && clazzParams.length != 0){
				sBuilder.deleteCharAt(sBuilder.length()-1);
			}
			sBuilder.append(")");
			System.out.println(sBuilder.toString());
		}
		
		System.out.println("===========begin methods list===========");
		Method[] methods = clazzProxy1.getMethods();
		for(Method method:methods){
			String name = method.getName();
			StringBuilder sBuilder = new StringBuilder(name);
			sBuilder.append("(");
			Class[] clazzParams = method.getParameterTypes();
			for(Class clazz:clazzParams){
				sBuilder.append(clazz.getName()).append(",");;
			}
			if(clazzParams!=null && clazzParams.length != 0){
				sBuilder.deleteCharAt(sBuilder.length()-1);
			}
			sBuilder.append(")");
			System.out.println(sBuilder.toString());
		}
		System.out.println("==============begin create instrance==============");
		Constructor construtor = clazzProxy1.getConstructor(InvocationHandler.class);
		
		class MyInvocationHandler1 implements InvocationHandler{

			@Override
			public Object invoke(Object arg0, Method arg1, Object[] arg2)
					throws Throwable {
				// TODO Auto-generated method stub
				return null;
			}
			
		}
		
		Collection proxy1 = (Collection)construtor.newInstance(new MyInvocationHandler1());
		System.out.println(proxy1);
		proxy1.clear();
		//proxy1.size();
		
		Collection proxy2 = (Collection)construtor.newInstance(new InvocationHandler(){
			@Override
			public Object invoke(Object arg0, Method arg1, Object[] arg2)
					throws Throwable {
				// TODO Auto-generated method stub
				return null;
			}
			
		});
		
		final ArrayList target  = new ArrayList();
		Collection proxy3 = (Collection)getProxy(target,new MyAdvise());
		proxy3.add("zxxx");
		proxy3.add("lhm");
		proxy3.add("bxm");
		System.out.println(proxy3.size());
		System.out.println(proxy3.getClass().getName());
	}

	private static Object getProxy(final Object target,final Advise advise) {
		Object proxy3 = Proxy.newProxyInstance(Collection.class.getClassLoader(), 
				/*new Class[]{Collection.class},*/
				target.getClass().getInterfaces(),
				new InvocationHandler(){
					
					@Override
					public Object invoke(Object proxy, Method method, Object[] args)
								throws Throwable {
					/*	long beginTime = System.currentTimeMillis();
						Object retVal  = method.invoke(target,args);
						long endTime = System.currentTimeMillis();
						System.out.println(method.getName()+" running time of "+(beginTime-endTime));
						return retVal;*/
						
						advise.beforeMethod(method);
						Object retVal  = method.invoke(target,args);
						advise.afterMethod(method);
						
						return retVal;
					}
						
					}
				);
		return proxy3;
	}

}
